{ "cells": [ { "metadata": {}, "cell_type": "markdown", "source": [ "# Numpy Code Cards\n", "## Try me\n", "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/ffraile/computer_science_tutorials/blob/main/source/Applied%20Mathematics/exercises/Numpy%20code%20cards.ipynb)[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/ffraile/computer_science_tutorials/main?labpath=source%2FApplied%20Mathematics%2Fexercises%2FNumpy%20code%20cards.ipynb)\n", "\n", "## How to use\n", "- Each card mirrors an A4 classroom prompt. **Predict first** (or discuss), then run the cell to check.\n", "- Detective cards show a buggy idea in Markdown; the code cell shows a **fixed** version.\n", "- Keep explanations short and schematic (*what* → *why*).\n", "\n", "### Turn Gemini into a coding tutor (no direct answers)\n", "Paste this in your first chat with Gemini to keep it in “tutor mode”:\n", "\n", "```markdown\n", "You are a **coding tutor** for Python in Jupyter/Colab. Follow the **course motto** “do not give up learning.”\n", "\n", "### Role & Goals\n", "- Use **Socratic guidance** and **test-first thinking** to help me solve problems myself.\n", "- Help me read errors, reason about state, and make small, safe iterations.\n", "\n", "### Strict Rules\n", "1) **Do not** provide full working solutions or paste complete functions/programs.\n", " - You may show **tiny illustrative fragments (≤3 lines)** or **pseudo-code with TODOs**, but not a drop-in answer.\n", "2) Prefer **questions over answers**; offer **one small next step** at a time.\n", "3) When debugging, explain **what the traceback says**, give **2–3 hypotheses**, and propose the **smallest diff** in *plain English* first.\n", "4) Encourage **TDD**: ask me to write/assert a test, predict, run, and report outputs.\n", "5) Keep responses concise (≈120–150 words) unless I ask for a deeper explanation or code review.\n", "6) Ask me to **run code and share results**; adapt based on the output.\n", "7) If I request the full solution, remind me of the rules and offer a **higher-tier hint** instead.\n", "8) When I finalize an exercise, reinforce learning lessons and suggest additional exercises\n", "\n", "### Interaction Loop (use this structure)\n", "- **Restate goal:** what I’m trying to accomplish in one line.\n", "- **Diagnose:** key assumption to check or error to interpret.\n", "- **Hint (tiered):**\n", " - Tier 1: Conceptual nudge (no code).\n", " - Tier 2: Directed hint (identify line/construct to change).\n", " - Tier 3: Pseudo-code with TODOs or a **1–3 line** pattern (still not a full solution).\n", "- **Next action:** one concrete step for me to try now.\n", "- **Ask back:** what to run/paste (output, test result, or traceback).\n", "\n", "### When reviewing my code\n", "- Comment on **correctness, clarity, naming, and complexity (big-O)**.\n", "- Suggest **tests** I’m missing (boundaries, empty cases, error paths).\n", "\n", "### Safety & Ethics\n", "- No secrets or private data in prompts.\n", "- avoid library functions/APIs unless I ask.\n", "\n", "Stay in tutor mode for the whole session.\n", "```\n", "\n", "## Code Cards\n", "1. Predict the output of this code:\n", "```python\n", "import numpy as np\n", "arr = np.array([[2, 4, 6], [8, 10, 12], [14, 16, 18]])\n", "print(arr[:2, :2])\n", "```\n" ], "id": "73d4cb1e6b491b2a" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": "", "id": "33493ecf0dee6f60" }, { "metadata": {}, "cell_type": "markdown", "source": [ "2. Predict the output of this code:\n", "```python\n", "import numpy as np\n", "arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n", "arr2 = arr.copy()\n", "arr2[0, 0] = 99\n", "print(arr2)\n", "```" ], "id": "675bafb25028de59" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": "", "id": "9f139d8d1addab64" }, { "metadata": {}, "cell_type": "markdown", "source": [ "3. Predict the output of this code:\n", "```python\n", "import numpy as np\n", "arr = np.array([[10, 20, 30], [40, 50, 60], [70, 80, 90]])\n", "arr2 = arr[arr > 20] + 2\n", "print(arr2)\n", "```" ], "id": "db7c4111d10f4d45" }, { "metadata": { "ExecuteTime": { "end_time": "2025-12-25T11:13:31.670086Z", "start_time": "2025-12-25T11:13:31.667120Z" } }, "cell_type": "code", "source": "", "id": "1dfe686792f3dc4e", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[32 42 52 62 72 82 92]\n" ] } ], "execution_count": 3 }, { "metadata": {}, "cell_type": "markdown", "source": [ "4. Predict the output of this code:\n", "```python\n", "import numpy as np\n", "arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n", "arr[1:, 1:] = arr[1:, 1:] * 10\n", "arr2 = arr[arr >= 20]\n", "print(arr2)\n", "```" ], "id": "1c70b1ed19929eb6" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": "", "id": "e8e5cecc80efc5b4" }, { "metadata": {}, "cell_type": "markdown", "source": [ "5. Predict the output of this code:\n", "```python\n", "import numpy as np\n", "Y = np.array([[2.0, 2.1, 2.2], [3.0, 3.1, 3.2], [4.0, 4.1, 4.2]])\n", "print(np.mean(Y, axis=0))\n", "```" ], "id": "c633422f1a1a4868" }, { "metadata": {}, "cell_type": "code", "source": "", "id": "2bfca0d6846aa064", "outputs": [], "execution_count": null }, { "metadata": {}, "cell_type": "markdown", "source": [ "6. Predict the output of this code:\n", "```python\n", "import numpy as np\n", "X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n", "print(np.sum(X, axis=1))\n", "```" ], "id": "45f21da6f5645263" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": "", "id": "2020201f0b9c1d4e" }, { "metadata": {}, "cell_type": "markdown", "source": [ "7. Predict the output of this code:\n", "```python\n", "import numpy as np\n", "X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n", "Y = X[1:, :2] + 5\n", "print(np.sum(Y, axis=0))\n", "```" ], "id": "eda132986b76803e" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": "", "id": "bd576e91ab525216" }, { "metadata": {}, "cell_type": "markdown", "source": [ "8. Find the bug in this code snippet that attempts to plot a sine wave using Numpy and Matplotlib:\n", "\n", "```python\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "x = np.linspace(0, 100, 2 * np.pi)\n", "y = np.sin(x)\n", "plt.plot(x, y)\n", "plt.show()\n", "```\n", "Hints: ```np.pi``` correctly represents the value of π in Numpy. ```np.linspace(a, b, n)``` generates n evenly spaced values from a to b, inclusive. ```np.sin(x)``` computes the sine of each element in the array x.\n" ], "id": "4c06ae4e1e741d45" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": "", "id": "ada18c711c4c912f" }, { "metadata": {}, "cell_type": "markdown", "source": [ "9. The code snippet below imports an image from the library scikit-image as a 3D numpy array where the first two dimensions represent width and height and the third dimension represents colour channels (index 0 represents red, index 1 represents green, and index 2 represents blue). Fill in the values of the missing code to plot only the red channel of the image as a gray colormap.\n", "```python\n", "import numpy as np\n", "from skimage import data\n", "import matplotlib.pyplot as plt\n", "cat = data.chelsea()\n", "# fill in the missing code here\n", "channel = ?\n", "plt.imshow(channel, cmap='gray')\n", "plt.show()\n", "```\n", "Hints: ```plt.imshow()``` displays an image. The argument ```cmap='gray'``` specifies that the image should be displayed in grayscale. The image data can be a 2D array for grayscale images or a 3D array for RGB images." ], "id": "25448012afa12579" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": "", "id": "e8d4e02a56c6b150" }, { "metadata": {}, "cell_type": "markdown", "source": [ "10. Predict the output of this code:\n", "```python\n", "import numpy as np\n", "arr = np.array([[2, 4, 6], [8, 10, 12], [14, 16, 18]])\n", "print(arr[arr % 4 == 0])\n", "```" ], "id": "45d3bdd4eb48bc67" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": "", "id": "6dc824c826fa8849" }, { "metadata": {}, "cell_type": "markdown", "source": [ "11. Find the bug in this code snippet that attempts to compute the product of a matrix containing sales data and a vector of prices using Numpy, and plot the total revenue. Rows in the sales matrix correspond to different months, and columns correspond to different products:\n", "\n", "**Prices vector**:\n", "\n", "| Product 1 | Product 2 | Product 3 |\n", "|-----------|-----------|-----------|\n", "| 2 | 4 | 6 |\n", "\n", "**Sales matrix**:\n", "\n", "| Month | Product 1 | Product 2 | Product 3 |\n", "|--------------|-----------|-----------|-----------|\n", "| 0 | 5 | 10 | 15 |\n", "| 1 | 20 | 25 | 30 |\n", "| 2 | 35 | 40 | 45 |\n", "\n", "The expected output is a plot of total revenue per month." ], "id": "a472f08e4b26a6fd" }, { "metadata": { "ExecuteTime": { "end_time": "2025-12-25T11:39:36.515987Z", "start_time": "2025-12-25T11:39:36.308902Z" } }, "cell_type": "code", "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "sales = np.array([[5, 10, 15], [20, 25, 30], [35, 40, 45]])\n", "prices = np.array([2, 4, 6])\n", "total_revenue = prices @ sales\n", "plt.plot(total_revenue)\n", "plt.xlabel('Month')\n", "plt.xticks([0, 1, 2])\n", "plt.ylabel('Total Revenue')\n", "plt.title('Total Revenue per Month')\n", "plt.show()" ], "id": "70782667b96013a2", "outputs": [ { "data": { "text/plain": [ "
" ], "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAHHCAYAAABZbpmkAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAVbNJREFUeJzt3Qd8zdf/P/BX9h4SGYhYQSQyaa2W1p6l1C7aarUqKKXotKlZSvHtt+1XW0HNKkWV2lsSIsSIFWSKbFn33v/jnP6Sf6JUQpLPHa/n43Er596be8+9id6X8z7DSKPRaEBERESkp4yV7gARERFRRWLYISIiIr3GsENERER6jWGHiIiI9BrDDhEREek1hh0iIiLSaww7REREpNcYdoiIiEivMewQERGRXmPYIdIz+/fvh5GRkfyTSCn/+9//5O/h6dOnle4KEcMOUXkQ/1MvzaU0AWT27NnYunVrpX0YFV5MTU1Ro0YNvPHGG7hz506FPz89vZdeekn+zOrXr//I2/fs2VP0c924cWOF9uWbb76Rv0tE2sxU6Q4Q6YOffvqpRPvHH3+UHzgPX9+oUaNShZ3XXnsNvXr1QmWYPn066tSpg5ycHBw/flx+cB0+fBjnz5+HpaVlpfSByk78bK5evYqTJ0/i+eefL3HbmjVr5O3iZ1rRRNipWrWqDMlE2ophh6gcvP766yXaIjSIsPPw9dqoS5cuaNq0qfz67bfflh9cX375JbZt24Z+/fop3T2DpFarkZeX969hs169eigoKMDatWtLhB0RcLZs2YJu3bph06ZNldRjIu3GMhZRJcnKysKHH36ImjVrwsLCAg0bNsSCBQug0WiK7iPKDuJ+q1evLipDFP6L+ebNm3j//ffl91lZWcHZ2Rl9+/bFjRs3yrWfL774ovwzJiamxPXR0dFyxMnJyUl+CIuAJAJRITE3Q/RX9P1hu3fvlrdt37696DpRKnvrrbfg5uYm3w9fX198//33j5x/9Msvv2DWrFnw8PCQz92uXTs5qlFc7dq1Hzm6IEo+4lJcbm4uvvjiC3h5ecnnFj+Tjz76SF7/JOKxGjdujDNnzqBly5byZyFGxlauXPmP+5b2ecRrDAkJkSMy4n0Q9921a9cT+zJw4ECsX79ehqNCv/32G7Kzsx8bVMPDw2XAtbe3h62trXwvRTh/VInzyJEjGD9+PFxcXGBjY4NXX30VSUlJJd7zqKgoHDhwoOj39VHv9b89BlFl4MgOUSUQgeaVV17BX3/9heHDhyMwMFAGgIkTJ8oP/cWLF8v7ibKXGF0R/1IfMWJE0b/ghVOnTuHo0aMYMGCA/NAXIWfFihXyw+XChQuwtrYul74WhqcqVaoUXSc+0Fq1aiXn9EyePFl+aIkAIkptYvRAfICJ8FO3bl15/bBhw0o8pvhAFo/XqVMn2U5ISEDz5s2LPuTFB+HOnTvle5Oeno4PPvigxPfPnTsXxsbGmDBhAtLS0jBv3jwMHjwYJ06cKPPrE8FA/CxEqU68x6K0GBkZKX8Gly9fLtV8qfv376Nr164yUIjAIV7zyJEjYW5uLgPc0zzPvn375OOI90OMrokg8SSDBg3C1KlTZShs27atvC40NFQGGFdX13/cX/wcRZgVQUeELjMzM6xatUr+DonA0qxZsxL3Hz16tPy5icAmfi+++uor2T/x8xREW9xHhKZPPvlEXifCa1keg6hSaIio3I0aNUoM1xS1t27dKtszZ84scb/XXntNY2RkpLl69WrRdTY2Npphw4b94zGzs7P/cd2xY8fk4/74449F1/3111/yOvHnv/nhhx/k/f78809NUlKSJjY2VrNx40aNi4uLxsLCQrYLtWvXTuPn56fJyckpuk6tVmtatmypqV+/ftF1U6ZM0ZiZmWlSUlKKrsvNzdU4Ojpq3nrrraLrhg8frqlWrZomOTm5RJ8GDBigcXBwKHqtha+lUaNG8nEKLVmyRF4fGRlZdF2tWrUe+b61adNGXgr99NNPGmNjY82hQ4dK3G/lypXyMY8cOfKv75t4LHG/hQsXlniNgYGBGldXV01eXl6Zn0e0xX2joqL+9bmL98HX11d+3bRpU/l+Cvfv39eYm5trVq9eXfTebdiwoej7evXqJW+PiYkpuu7u3bsaOzs7TevWrf/xu9G+fXv5cy40btw4jYmJiSY1NbXoOtGP4u/v0zwGUUVjGYuoEvz+++8wMTHBmDFjSlwvylris06MajyJKJcUys/Px71792R5xNHREWFhYU/dt/bt28uRFVFiEWUqMWojylNi9EhISUmRow5iFCMjIwPJycnyIp5fjNRcuXKlaPVW//79Zd82b95c9Ph//PEHUlNT5W2CeL1iNKhHjx7y68LHExfxeGLk5uHX8+abb8pRk4dLbdeuXSvz692wYYMcZfH29i7x3IUjI2L07UnEyrV33323qC36JtqJiYmyvPU0z9OmTRv4+PiU+fWI0R3xfos5PmLllfg9EyNtD1OpVPJnIUbjxAhcoWrVqsnHECNQYlStODEiJUbfir/v4nFESbW0yuMxiJ4Vy1hElUD8j7169eqws7N75Oqs0vyP/8GDB5gzZw5++OEHGS6Kz/URAeFpLV++HA0aNJCPIebMHDx4UM4ZKSTmxojn+uyzz+TlUcSHvChxBQQEyA93UaIQJSlBfC3KMoUf8mK+hgg///nPf+TlcY9XnKenZ4l2YYlNlJPKSoSzixcvyoBXmud+FPGzFKGwOPEeCqJUI0p0ZX0eMe/naYiypijvicAs5vx07979H79nhe+7mMsj5nw9TPweirJbbGysnDNUnu97ef7siJ4Www6RjhBzH0TQEfNZWrRoAQcHB/kvZvFhV3yCalmJ+UGFq7HEv/pfeOEF+S/9S5cuybkYhY8tPlAL59w8TIwwFRIjOGIysRjFEB+6YpRIzGsRoyFC4eOJlWoPz+0p5O/vX6ItRise5eHJ3Y8iRhGKf794fj8/PyxatOiR9xcjXOWhrM9TfOSuLMTIjJhzs3DhQjmhuDxXYJXmfa+MxyB6Vgw7RJWgVq1a+PPPP2UZqPi/usUKp8Lbn/ShLUoUIhyID7Xiy4zFKEl5ER9MYvTo5ZdfxrJly+Rk5MKSh5jMKkpeTyLCzrRp0+SHrpisKkojIpAVEiMd4j0QIaQ0j1daYsTgUe+FGDUrXrYRE77Pnj0rJ/E+7r1+krt378pVc8VHd8SkY6FwYnF5PE9piXAqJraLkqaYOP0o4n0Xk9hFiH2Y+D0UE8CfJuhV9GsjKg+cs0NUCcQHkPhwFwGiOLEyR3xYiKXAhcQH6KM+tEUQefhfw19//bV83PIkRgnEaI9YNSPClFjVI64Tq3bi4uL+cf+HlxGLkogY0RDlK3ERIw+tW7cu8Tr69Okjw5DYuPBJj1daIlyIJdRi7kohsdRdlGaKE3OPRBnw22+/fWSpUISYJxH724j3o5B4TtEWgaJJkybl9jylJeZaidVOYoO/4nObihPve8eOHfHrr7+W2K5ArIwTK7jEiJ5YpVVWj/t9JdImHNkhqgRiMq4YLRHLc8UHjZjbIiaLig8eUZYqXF4uiA9LMQokyh9iboiYyyGWBIu5GGJpuihfiYmsx44dk/cT++2UN7EkXuzhI/Zbee+99+S8HvFhKELMO++8I0dKxIek6MPt27flCMbDozuff/653BNHzN0RowYPLyUXE3TF6xKPJ16PmAgtJiaL1yS+LisxsiFGvzp37iyDhtgn6Oeffy7x3gpDhgyRS7zF6xJ9EEvqRWAUoxvierElQGFZ73HEz0VsvCh+lmKujgh1ERERcg6SGAErr+cpLfE7IZagP8nMmTPlZpfiZyn2bBKlRRHSxF44Yjn/0xC/r2ILBPHYopwpwnHh/CwirVHh672IDNDDS8+FjIwMuey2evXqcnm2WLI9f/78EstyhejoaLkM2MrKSj5G4XJqsaz4zTff1FStWlVja2ur6dSpk7zvw0uuy7r0/NSpU/+4TaVSaerVqycvBQUF8jqxXHno0KEad3d32f8aNWpounfvLperP+zKlSvyscXl8OHDj3z+hIQE+T7VrFlTPp54XLHE/T//+c8/Xkvx5dPC9evX5fXiNRQnloOLfoml861atdKcPn36H0vPBbE8/Msvv5TLpsV9q1SpomnSpIlm2rRpmrS0tFIt+xaP3aJFC42lpaX8GSxbtuwf9y3t84jXIt6L0iq+9PxxHvfehYWFyd8d8TtkbW2tefnllzVHjx4t1e/Go3634uPjNd26dZPL18Vthe91WR6DqKIZif8oHbiIiHSFKOmJydePKsERkXbinB0iIiLSaww7REREpNcYdoiIiEivcc4OERER6TWO7BAREZFeY9ghIiIivcZNBf/vDBux/bvYwp5bnxMREekGMRNHHMMjNvp8ePPS4hh2/u+cm/I6/I+IiIgqlzgWxsPD47G3M+wARQczijfrac6GISIiosonDhoWgxXFD1h+FIadYqf2iqDDsENERKRbnjQFhROUiYiISK8x7BAREZFeY9ghIiIivcawQ0RERHqNYYeIiIj0GsMOERER6TWGHSIiItJrDDtERESk1xh2iIiISK8x7BAREZFe05qwM3fuXLnd8wcffCDbKSkpGD16NBo2bAgrKyt4enpizJgxSEtLK/F9t27dQrdu3WBtbQ1XV1dMnDgRBQUFCr0KIiIi0jZacTbWqVOnsGrVKvj7+5c4iVxcFixYAB8fH9y8eRPvvfeevG7jxo3yPiqVSgYdd3d3HD16FHFxcRg6dCjMzMwwe/ZsBV8RERERaQsjjUajUbID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61alu0RkUObMmYPnnntOnk7g6uqKXr164dKlS4r0hWGngqxfvx7jx4+Xy+3CwsIQEBCATp06ITExUemuERmErKws+fdO/KODiCrfgQMHMGrUKBw/fhx79uxBfn4+OnbsKP9uVjYuPa8gYiRHJNply5YVnb8lzgYZPXo0Jk+erHT3iAyKGNnZsmWL/JclESkjKSlJjvCIENS6detKfW6O7FSAvLw8nDlzBu3bty9x/pZoHzt2TNG+ERERKSEtLU3+6eTkVOnPzbBTAZKTk6FSqeDm5lbietGOj49XrF9ERERKENWNDz74AK1atULjxo0r/fl56jkRERFVKDF35/z58zh8+DCUwLBTAapWrQoTExMkJCSUuF603d3dFesXERFRZQsJCcH27dvlCkkPDw8ogWWsCmBubo4mTZpg7969JYbwRLtFixaK9o2IiKgyiPVPIuiIxQH79u1DnTp1oBSO7FQQsex82LBhaNq0KZ5//nl89dVXcrndm2++qXTXiAxCZmYmrl69WtS+fv06IiIi5ORIT09PRftGZCilq9DQUPz6669yr53COasODg6wsrKq1L5w6XkFEsvO58+fL3/AgYGBWLp0qVySTkQVb//+/Xj55Zf/cb34R8j//vc/RfpEZGhbPjzKDz/8gDfeeAOViWGHiIiI9Brn7BAREZFeY9ghIiIivcawQ0RERHqNYYeIiIj0GsMOERER6TWGHSIiItJrDDtERESk1xh2iIgesyHa1q1ble4GEZUDhh0i0ipiZ1URNN57771Hbj8vbivP3VenTp0qdzgnIv3FsENEWqdmzZpYt24dHjx4UHRdTk6OPGeH51oRUVkx7BCR1gkODpaBZ/PmzUXXia9F0AkKCiq6Ljc3F2PGjIGrqyssLS3xwgsv4NSpUyXOxxIjQXv37pWH8lpbW6Nly5a4dOmSvF2ckTVt2jScPXtW3k9cip+blZycjFdffVV+X/369bFt27ZKew+IqPww7BCRVnrrrbfkgYGFvv/+e7z55psl7vPRRx9h06ZNWL16NcLCwuDl5YVOnTohJSWlxP0++eQTLFy4EKdPn4apqal8bKF///748MMP4evri7i4OHkR1xUSQahfv344d+4cunbtisGDB//jsYlI+zHsEJFWev3113H48GHcvHlTXo4cOSKvK5SVlYUVK1Zg/vz56NKlC3x8fPDtt9/CysoK3333XYnHmjVrFtq0aSPvM3nyZBw9elSWxcR9bW1tZQByd3eXF3FdITE3aODAgTJEzZ49G5mZmTh58mSlvg9E9OxMy+ExiIjKnYuLC7p16ybLShqNRn5dtWrVottjYmKQn5+PVq1aFV1nZmaG559/HhcvXizxWP7+/kVfV6tWTf6ZmJj4xPk/xb/PxsYG9vb28vuISLcw7BCR1hLlppCQEPn18uXLn/pxRAgqJOblCGq1ukzfV/i9pfk+ItIuLGMRkdbq3Lkz8vLy5AiOmItTXL169WBubi7LW4XE/cQEZVGuKi3xGCqVqlz7TUTahSM7RKS1TExMikpS4uviRFlp5MiRmDhxIpycnGRJat68ecjOzsbw4cNL/Ry1a9fG9evXERERAQ8PD9jZ2cHCwqLcXwsRKYdhh4i0mpgn8zhz586VZaUhQ4YgIyNDLi/fvXs3qlSpUurH79Onj1zW/vLLLyM1NVWuACvPTQuJSHlGGjHzj4iIiEhPcc4OERER6TWGHSIiItJrDDtERESk1xh2iIiISK8x7BAREZFeY9ghIiIivcawQ0RERHqNYYeIiIj0GsMOERER6TWGHSIiItJrDDtERESk1xh2iIiICPrs/wFoDZBJGhpTUwAAAABJRU5ErkJggg==" }, "metadata": {}, "output_type": "display_data" } ], "execution_count": 5 }, { "metadata": {}, "cell_type": "markdown", "source": [ "12. Optimize this code snippet that computes the total revenues per sales per product over a year. The sales data is stored in a 2D array where rows represent months and columns represent products:\n", "\n", "**Sales matrix**:\n", "\n", "| Month | Product 1 | Product 2 | Product 3 |\n", "|--------------|-----------|-----------|-----------|\n", "| 0 | 100 | 200 | 300 |\n", "| 1 | 150 | 250 | 350 |\n", "| 2 | 200 | 300 | 400 |\n", "| 3 | 250 | 350 | 450 |\n", "| 4 | 300 | 400 | 500 |\n", "| 5 | 350 | 450 | 550 |\n", "| 6 | 400 | 500 | 600 |\n", "| 7 | 450 | 550 | 650 |\n", "| 8 | 500 | 600 | 700 |\n", "| 9 | 550 | 650 | 750 |\n", "| 10 | 600 | 700 | 800 |\n", "| 11 | 650 | 750 | 850 |\n", "\n", "\n", "**Product prices**\n", "\n", "| Product 1 | Product 2 | Product 3 |\n", "|-----------|-----------|-----------|\n", "| 2 | 4 | 6 |\n", "\n" ], "id": "505a573cf0e04a86" }, { "metadata": { "ExecuteTime": { "end_time": "2025-12-25T09:35:35.766460Z", "start_time": "2025-12-25T09:35:35.728287Z" } }, "cell_type": "code", "source": [ "import numpy as np\n", "sales = np.array([[100, 200, 300], [150, 250, 350], [200, 300, 400], [250, 350, 450],\n", " [300, 400, 500], [350, 450, 550], [400, 500, 600], [450, 550, 650],\n", " [500, 600, 700], [550, 650, 750], [600, 700, 800], [650, 750, 850]])\n", "\n", "prices = np.array([2, 4, 6])\n", "\n", "revenues = np.zeros(sales.shape[1])\n", "for j in range(sales.shape[1]):\n", " total = 0\n", " for i in range(sales.shape[0]):\n", " total += sales[i, j] * prices[j]\n", " revenues[j] = total\n", "print(revenues)" ], "id": "a7934e1b9282e3de", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 9000. 22800. 41400.]\n" ] } ], "execution_count": 1 }, { "metadata": {}, "cell_type": "markdown", "source": [ "13. The code snippet below attempts to filter a 2D numpy array to extract sales data greater than a given threshold value, and then compute the sales of products 2 and 3, but can be optimized for performance. Rewrite the code to improve its efficiency.\n", "\n", "**Sales matrix**:\n", "\n", "| Month | Product 1 | Product 2 | Product 3 |\n", "|--------------|-----------|-----------|-----------|\n", "| 0 | 100 | 200 | 300 |\n", "| 1 | 150 | 250 | 350 |\n", "| 2 | 200 | 300 | 400 |\n", "| 3 | 250 | 350 | 450 |\n", "| 4 | 300 | 400 | 500 |\n", "| 5 | 350 | 450 | 550 |\n", "| 6 | 400 | 500 | 600 |\n", "| 7 | 450 | 550 | 650 |\n", "| 8 | 500 | 600 | 700 |\n", "| 9 | 550 | 650 | 750 |\n", "| 10 | 600 | 700 | 800 |\n", "| 11 | 650 | 750 | 850 |\n", "\n", "**Product prices**\n", "| Product 1 | Product 2 | Product 3 |\n", "|-----------|-----------|-----------|\n", "| 2 | 4 | 6 |\n", "\n", "```python\n", "import numpy as np\n", "sales = np.array([[100, 200, 300], [150, 250, 350], [200, 300, 400], [250, 350, 450],\n", " [300, 400, 500], [350, 450, 550], [400, 500, 600], [450, 550, 650],\n", " [500, 600, 700], [550, 650, 750], [600, 700, 800], [650, 750, 850]])\n", "threshold = 400\n", "prices = np.array([2, 4, 6])\n", "revenues = sales[:, 1][sales[:, 1] > threshold] * prices[1]\n", "revenues += sales[:, 2][sales[:, 2] > threshold] * prices[2]\n", "print(revenues)\n", "```" ], "id": "2f24c811443682f0" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": "", "id": "846d44b294351127" } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.6" } }, "nbformat": 4, "nbformat_minor": 5 }